﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Reflection;
using System.IO;
using System.Collections;
using System.Data.SqlClient;
using System.Text.RegularExpressions;
using Microsoft.Win32;

namespace CSP.Package.Controls
{
    public partial class FBADatabase : UserControl, IInstallationControl
    {
        //default value, it will be overwrite by the installer
        string conStr = "packet size=4096;integrated security=SSPI;" +
                    "data source=\"(local)\";persist security info=False;" +
                    "initial catalog=master";

        const string database_installscript_file = "fba_database_install.txt";
        const string database_uninstallscript_file = "fba_database_uninstall.txt";

        public FBADatabase()
        {
            InitializeComponent();
        }

        private static string GetScript(string name)
        {
            Assembly asm = Assembly.GetExecutingAssembly();
            Stream str = asm.GetManifestResourceStream(asm.GetName().Name + "." + name);

            StreamReader reader = new StreamReader(str);
            return reader.ReadToEnd();
        }

        private string GetConnetionString()
        {
            if (txbServer.Text.Length == 0)
                return string.Empty;
            if (rdbConnectionWindows.Checked)
                return string.Format("server={0};Trusted_Connection=yes", txbServer.Text);
            else
            {
                if (txbPassword.Text.Length == 0 || txbUsername.Text.Length == 0)
                    return string.Empty;
                return string.Format("server={0};User ID={1};Password={2}", new string[] { txbServer.Text, txbUsername.Text, txbPassword.Text });
            }
            
        }

        private static void ExecuteSql(SqlConnection sqlCon)
        {

            string[] SqlLine;
            Regex regex = new Regex("^GO", RegexOptions.IgnoreCase | RegexOptions.Multiline);

            string txtSQL = GetScript(database_installscript_file);
            SqlLine = regex.Split(txtSQL);

            SqlCommand cmd = sqlCon.CreateCommand();
            cmd.Connection = sqlCon;

            foreach (string line in SqlLine)
            {
                if (line.Length > 0)
                {
                    cmd.CommandText = line;
                    cmd.CommandType = CommandType.Text;
                    try
                    {
                        cmd.ExecuteNonQuery();
                    }
                    catch (Exception sqlex)
                    {
                        //rollback
                        ExecuteDrop(sqlCon);
                        break;
                    }
                }
            }

            if (RegistryAccess.PropertyExists(Registry.LocalMachine, Constants.CspRegistryKey, "CSPInternetIdentity"))
            {
                string InternetIdentity = RegistryAccess.GetStringProperty(Registry.LocalMachine, Constants.CspRegistryKey, "CSPInternetIdentity");

                cmd.CommandText = string.Format("IF NOT EXISTS (SELECT * FROM sys.server_principals WHERE name = N'{0}') CREATE LOGIN [{0}] FROM WINDOWS WITH DEFAULT_DATABASE=[master], DEFAULT_LANGUAGE=[us_english]; EXEC sp_addrolemember N'db_owner', N'{0}'", InternetIdentity);
                cmd.CommandType = CommandType.Text;
                try
                {
                    cmd.ExecuteNonQuery();
                }
                catch (Exception ex)
                {
                }
            }
            if (RegistryAccess.PropertyExists(Registry.LocalMachine, Constants.CspRegistryKey, "CentralAdminIdentity"))
            {
                string CentralAdminIdentity = RegistryAccess.GetStringProperty(Registry.LocalMachine, Constants.CspRegistryKey, "CentralAdminIdentity");

                cmd.CommandText = string.Format("IF NOT EXISTS (SELECT * FROM sys.server_principals WHERE name = N'{0}') CREATE LOGIN [{0}] FROM WINDOWS WITH DEFAULT_DATABASE=[master], DEFAULT_LANGUAGE=[us_english]; EXEC sp_addrolemember N'db_owner', N'{0}'", CentralAdminIdentity);
                cmd.CommandType = CommandType.Text;
                try
                {
                    cmd.ExecuteNonQuery();
                }
                catch (Exception ex)
                {
                }
            }
                string anonymousIdentity = @"NT AUTHORITY\NETWORK SERVICE";

                cmd.CommandText = string.Format("IF NOT EXISTS (SELECT * FROM sys.server_principals WHERE name = N'{0}') CREATE LOGIN [{0}] FROM WINDOWS WITH DEFAULT_DATABASE=[master], DEFAULT_LANGUAGE=[us_english]; EXEC sp_addrolemember N'db_owner', N'{0}'", anonymousIdentity);
                cmd.CommandType = CommandType.Text;
                try
                {
                    cmd.ExecuteNonQuery();
                }
                catch (Exception ex)
                {
                }

        }

        private static void ExecuteDrop(SqlConnection sqlCon)
        {
            if (sqlCon.State != ConnectionState.Closed) sqlCon.Close();
            sqlCon.Open();
            SqlCommand cmd = sqlCon.CreateCommand();
            cmd.Connection = sqlCon;
            cmd.CommandText = GetScript(database_uninstallscript_file);
            cmd.CommandType = CommandType.Text;
            cmd.ExecuteNonQuery();
            sqlCon.Close();
        }

        public bool Install()
        {
            try
            {
                conStr = GetConnetionString();
                if (conStr != string.Empty)
                {

                    RijndaelCryptography rijndael = new RijndaelCryptography();
                    rijndael.GenKey();
                    rijndael.Encrypt(conStr);
                    SqlConnection sqlCon = new SqlConnection(conStr);

                    sqlCon.Open();
                    ExecuteSql(sqlCon);
                    if (sqlCon.State != ConnectionState.Closed) sqlCon.Close();
                    // TODO

                    RegistryAccess.CreateStringProperty(Registry.LocalMachine, Constants.CspRegistryKey, "FBAConnectionString", conStr + ";Initial Catalog=aspnetdb");
                    return true;
                }
            }
            catch (Exception ex)
            {
                GetForm().ShowException(ex);
            }
            return false;

        }


        #region IInstallationControl Members

        protected Installer _form;
        public Installer GetForm()
        {
            return _form;
        }

        public void SetForm(Installer installer)
        {
            _form = installer;
        }

        private bool ValidateInputs()
        {
            if (txbServer.Text.Equals(string.Empty))
            {
                MessageBox.Show(CSP.Package.labels.CspInstallError_ServerNoEmpty, CSP.Package.labels.CspInstallError_Title, MessageBoxButtons.OK, MessageBoxIcon.Error);
                txbServer.Focus();
                txbServer.Select();
                return false;
            }
            if (rdbConnectionSQL.Checked && txbUsername.Text.Equals(string.Empty))
            {
                MessageBox.Show(CSP.Package.labels.CspInstallError_UsernameNoEmpty, CSP.Package.labels.CspInstallError_Title, MessageBoxButtons.OK, MessageBoxIcon.Error);
                txbUsername.Focus();
                txbUsername.Select();
                return false;
            }
            if (rdbConnectionSQL.Checked && txbPassword.Text.Equals(string.Empty))
            {
                if (MessageBox.Show(CSP.Package.labels.CspInstallError_PasswordNoEmpty, CSP.Package.labels.CspInstallError_Title, MessageBoxButtons.YesNo, MessageBoxIcon.Warning) != DialogResult.Yes)
                {
                    txbPassword.Focus();
                    txbPassword.Select();
                    return false;
                }
            }
            if (rdbConnectionSQL.Checked && !txbPassword.Text.Equals(txbPassword2.Text))
            {
                MessageBox.Show(CSP.Package.labels.CspInstallError_PasswordNoMatch, CSP.Package.labels.CspInstallError_Title, MessageBoxButtons.OK, MessageBoxIcon.Error);
                txbPassword.Focus();
                txbPassword.Select();
                return false;
            }
            return true;
        }
        public bool Next()
        {

            if (ValidateInputs())
                return Install();
            else
                return false;


        }


        public void Previous()
        {
        }

        public void Skip()
        {
        }

        #endregion

        private void SimpleCMSDatabase_Load(object sender, EventArgs e)
        {
            this.rdbConnectionWindows.Checked = true;
            this.txbPassword.Enabled = false;
            this.txbUsername.Enabled = false;
            this.txbPassword2.Enabled = false;
        }

        private void rdbConnectionSQL_CheckedChanged(object sender, EventArgs e)
        {
            this.txbUsername.Enabled = rdbConnectionSQL.Checked;
            this.txbPassword.Enabled = rdbConnectionSQL.Checked;
            this.txbPassword2.Enabled = rdbConnectionSQL.Checked;

        }

        private void FBADatabase_Load(object sender, EventArgs e)
        {
            TranslateLiterals();            
        }

        private void TranslateLiterals()
        {
            richTextBox1.Text = CSP.Package.labels.FBADatabase_Intro;

            groupBox1.Text = CSP.Package.labels.FBADatabaseCredentials_GroupBox;
          
            label1.Text = CSP.Package.labels.ServerName_Label;
            label5.Text = CSP.Package.labels.Username_Label;
            label6.Text = CSP.Package.labels.Password_Label;
            label2.Text = CSP.Package.labels.PasswordReType_Label;

            this.rdbConnectionWindows.Text = CSP.Package.labels.ConnectionWindows_Label;
            this.rdbConnectionSQL.Text = CSP.Package.labels.ConnectionSQL_Label;
        }
    }
}
